/**
 * 微信小程序第三方平台上传管理器
 * 使用 miniprogram-ci 实现代小程序上传
 */
const ci = require('miniprogram-ci');
const path = require('path');
const fs = require('fs-extra');
const config = require('../../config/miniprogram.config');
const logManager = require('./logManager');

class MiniprogramUploadManager {
  constructor() {
    this.config = config;
  }

  /**
   * 创建第三方平台项目实例
   * @param {string} projectPath - 小程序项目路径
   * @param {string} appid - 授权小程序的 appid
   * @param {string} accessToken - 第三方平台的 access_token (可选,优先使用 appSecret)
   * @returns {Promise<Project>}
   */
  async createProject(projectPath, appid, accessToken = null) {
    try {
      logManager.sendLog('miniprogram-upload', {
        level: 'info',
        message: '📱 创建第三方平台小程序项目实例',
        data: { projectPath, appid }
      });

      // 确保项目路径存在
      if (!await fs.pathExists(projectPath)) {
        throw new Error(`项目路径不存在: ${projectPath}`);
      }

      // 检查是否存在 project.config.json
      const projectConfigPath = path.join(projectPath, 'project.config.json');
      if (!await fs.pathExists(projectConfigPath)) {
        throw new Error('未找到 project.config.json 文件');
      }

      // 读取项目配置
      const projectConfig = await fs.readJson(projectConfigPath);

      // 第三方平台模式配置
      const projectOptions = {
        appid: appid, // 授权小程序的 appid
        type: 'miniProgram',
        projectPath: projectPath,
        ignores: ['node_modules/**/*'], // 忽略文件
      };

      // 优先使用开发小程序的私钥（如果是开发小程序）
      if (this.config.devMiniprogram && appid === this.config.devMiniprogram.appId) {
        const privateKeyPath = this.config.devMiniprogram.privateKeyPath;
        if (await fs.pathExists(privateKeyPath)) {
          projectOptions.privateKeyPath = privateKeyPath;
          logManager.sendLog('miniprogram-upload', {
            level: 'info',
            message: '🔑 使用开发小程序私钥认证'
          });
        } else {
          throw new Error(`开发小程序私钥文件不存在: ${privateKeyPath}`);
        }
      }
      // 第三方平台使用 access_token 方式
      else if (accessToken) {
        projectOptions.token = accessToken;
        logManager.sendLog('miniprogram-upload', {
          level: 'info',
          message: '🔑 使用第三方平台 access_token 认证'
        });
      } else {
        throw new Error('缺少认证信息: 需要提供开发小程序私钥或第三方平台 accessToken');
      }

      const project = new ci.Project(projectOptions);

      logManager.sendLog('miniprogram-upload', {
        level: 'info',
        message: '✅ 第三方平台项目实例创建成功'
      });

      return project;

    } catch (error) {
      logManager.sendLog('miniprogram-upload', {
        level: 'error',
        message: '❌ 创建第三方平台项目实例失败',
        data: { error: error.message }
      });
      throw error;
    }
  }

  /**
   * 上传小程序代码到微信平台
   * @param {string} projectPath - 小程序项目路径
   * @param {string} authAppid - 授权小程序的 appid
   * @param {object} options - 上传选项
   * @returns {Promise<object>}
   */
  async upload(projectPath, authAppid, options = {}) {
    try {
      logManager.sendLog('miniprogram-upload', {
        level: 'info',
        message: '🚀 开始上传小程序代码',
        data: { projectPath, authAppid, options }
      });

      // 创建项目实例
      const project = await this.createProject(
        projectPath,
        authAppid,
        options.accessToken
      );

      // 合并上传配置
      const uploadOptions = {
        version: options.version || this.config.upload.version,
        desc: options.desc || this.config.upload.desc,
        setting: {
          ...this.config.upload.setting,
          ...(options.setting || {})
        },
        robot: options.robot || this.config.upload.robot,
        threads: options.threads || this.config.upload.threads,
        onProgressUpdate: (info) => {
          logManager.sendLog('miniprogram-upload', {
            level: 'info',
            message: `📤 上传进度: ${info.status}`,
            data: info
          });
        }
      };

      // 第三方平台模式需要指定 ext.json 配置
      if (options.extConfig) {
        uploadOptions.ext = {
          extEnable: true,
          extAppid: authAppid,
          ext: options.extConfig
        };
      }

      logManager.sendLog('miniprogram-upload', {
        level: 'info',
        message: '📦 开始执行上传...',
        data: { uploadOptions }
      });

      // 执行上传
      const uploadResult = await ci.upload({
        project,
        ...uploadOptions
      });

      logManager.sendLog('miniprogram-upload', {
        level: 'info',
        message: '✅ 小程序代码上传成功',
        data: uploadResult
      });

      return {
        success: true,
        result: uploadResult,
        appid: authAppid,
        version: uploadOptions.version,
        desc: uploadOptions.desc
      };

    } catch (error) {
      logManager.sendLog('miniprogram-upload', {
        level: 'error',
        message: '❌ 小程序代码上传失败',
        data: { error: error.message, stack: error.stack }
      });

      return {
        success: false,
        error: error.message,
        stack: error.stack
      };
    }
  }

  /**
   * 预览小程序
   * @param {string} projectPath - 小程序项目路径
   * @param {string} authAppid - 授权小程序的 appid
   * @param {object} options - 预览选项
   * @returns {Promise<object>}
   */
  async preview(projectPath, authAppid, options = {}) {
    try {
      logManager.sendLog('miniprogram-upload', {
        level: 'info',
        message: '🔍 开始生成预览二维码',
        data: { projectPath, authAppid }
      });

      // 创建项目实例
      const project = await this.createProject(
        projectPath,
        authAppid,
        options.accessToken
      );

      // 合并预览配置
      const previewOptions = {
        qrcodeFormat: options.qrcodeFormat || this.config.preview.qrcodeFormat,
        qrcodeOutputDest: options.qrcodeOutputDest || this.config.preview.qrcodeOutputDest,
        pagePath: options.pagePath || this.config.preview.pagePath,
        searchQuery: options.searchQuery || this.config.preview.searchQuery,
        scene: options.scene || this.config.preview.scene,
        robot: options.robot || this.config.preview.robot,
        onProgressUpdate: (info) => {
          logManager.sendLog('miniprogram-upload', {
            level: 'info',
            message: `🔍 预览进度: ${info}`,
            data: info
          });
        }
      };

      // 第三方平台模式配置
      if (options.extConfig) {
        previewOptions.ext = {
          extEnable: true,
          extAppid: authAppid,
          ext: options.extConfig
        };
      }

      // 执行预览
      const previewResult = await ci.preview({
        project,
        ...previewOptions
      });

      logManager.sendLog('miniprogram-upload', {
        level: 'info',
        message: '✅ 预览二维码生成成功',
        data: { qrcodePath: previewOptions.qrcodeOutputDest }
      });

      return {
        success: true,
        result: previewResult,
        qrcodePath: previewOptions.qrcodeOutputDest,
        appid: authAppid
      };

    } catch (error) {
      logManager.sendLog('miniprogram-upload', {
        level: 'error',
        message: '❌ 生成预览二维码失败',
        data: { error: error.message }
      });

      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取上传历史
   * @param {string} projectPath - 小程序项目路径
   * @param {string} authAppid - 授权小程序的 appid
   * @param {object} options - 选项
   * @returns {Promise<object>}
   */
  async getUploadHistory(projectPath, authAppid, options = {}) {
    try {
      // 创建项目实例
      const project = await this.createProject(
        projectPath,
        authAppid,
        options.accessToken
      );

      // 获取上传历史
      const history = await ci.getHistory({
        project
      });

      logManager.sendLog('miniprogram-upload', {
        level: 'info',
        message: '📋 获取上传历史成功',
        data: { count: history.length }
      });

      return {
        success: true,
        history
      };

    } catch (error) {
      logManager.sendLog('miniprogram-upload', {
        level: 'error',
        message: '❌ 获取上传历史失败',
        data: { error: error.message }
      });

      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 生成版本号
   * @returns {string}
   */
  generateVersion() {
    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0');
    const day = String(now.getDate()).padStart(2, '0');
    const hour = String(now.getHours()).padStart(2, '0');
    const minute = String(now.getMinutes()).padStart(2, '0');

    return `${year}.${month}${day}.${hour}${minute}`;
  }

  /**
   * 批量上传多个授权小程序
   * @param {string} projectPath - 小程序项目路径
   * @param {Array} authAppids - 授权小程序 appid 列表
   * @param {object} options - 上传选项
   * @returns {Promise<Array>}
   */
  async batchUpload(projectPath, authAppids, options = {}) {
    const results = [];

    for (const authAppid of authAppids) {
      logManager.sendLog('miniprogram-upload', {
        level: 'info',
        message: `🔄 批量上传: ${authAppid} (${authAppids.indexOf(authAppid) + 1}/${authAppids.length})`
      });

      const result = await this.upload(projectPath, authAppid, options);
      results.push({
        appid: authAppid,
        ...result
      });

      // 上传间隔,避免频率限制
      if (authAppids.indexOf(authAppid) < authAppids.length - 1) {
        await new Promise(resolve => setTimeout(resolve, 2000));
      }
    }

    return results;
  }
}

module.exports = new MiniprogramUploadManager();
